package utils

import (
	"GoAdmin/utils/logs"
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/beego/beego/v2/core/config"
	"github.com/disintegration/imaging"
	"github.com/golang/freetype"
	"github.com/nfnt/resize"
	"github.com/spf13/cast"
	"go.uber.org/zap"
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"
	"io/ioutil"
	"log"
	"math"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"time"
	"unicode/utf8"
)

//var fontTypes *truetype.Font

var (
	AnHuiServiceURL      = "https://yoxueche.ahjtpx.com/"
	AnHuiServiceLoginURL = "https://yoxueche.ahjtpx.com/login/login.do"
)

//保留浮点数N位小数

func Decimal(value float64, n string) float64 {
	//value, _ = strconv.ParseFloat(fmt.Sprintf("%."+n+"f", value), 64)
	//return value
	floatStr := fmt.Sprintf("%."+n+"f", value)
	value, _ = strconv.ParseFloat(floatStr, 64)
	return value
}

func RoundFloat(f float64, n int) float32 {
	n10 := math.Pow10(n)
	return float32(math.Trunc((f+0.5/n10)*n10) / n10)
}

// PostForm 发送http post请求数据为form
func PostForm(url string, data url.Values) (string, error) {
	resp, err := http.PostForm(url, data)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(content), nil
}

func SliceContains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func RandomCode(size int) string {
	var (
		str    = "0123456789"
		bytes  = []byte(str)
		result []byte
	)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < size; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

// AnHuiServiceAPIURLRequest 获取token后请求公众服务平台接口，并获取请求结果
func AnHuiServiceAPIURLRequest(apiURL, method, code string, data map[string]interface{}) (map[string]interface{}, error) {
	token, err := GetAnHuiSchooolLoginToken(method, code)
	if err != nil {
		return nil, err
	}
	RequestRUL := fmt.Sprintf("%s%s?token=%s", AnHuiServiceURL, apiURL, token)
	return APIReq(RequestRUL, data, method)
}

// GetAnHuiSchooolLoginService 安徽地区公众服务平台请求接口
func GetAnHuiSchooolLoginToken(method, code string) (string, error) {
	Key := fmt.Sprintf("school:%s:login", code)
	if exist := Exists(Key); !exist {
		// account, ok := AnHuiSchoolAccount[code]
		// if !ok {
		// 	return "", errors.New("登录账号密码不存在")
		// }
		// fmt.Println(account)

		data := map[string]interface{}{
			"uname": "wz_hhjs",
			"pwd":   "hhjs240430",
		}
		fmt.Println(data)
		logs.ZapLogs.Info("登录接口", zap.String("data", data["uname"].(string)))
		resp, err := APIReq(AnHuiServiceLoginURL, data, method)
		if err != nil {
			return "", err
		}
		if cast.ToInt(resp["errorcode"]) == 0 {
			if err := Set(Key, resp, 15*60*60); err != nil {
				return "", err
			}
			return cast.ToString(resp["token"]), nil
		}
		return "", errors.New(cast.ToString(resp["message"]))
	}
	dataBytes, err := Get(Key)
	if err != nil {
		fmt.Println(err.Error(), "redis get")
		return "", err
	}
	data := make(map[string]interface{}, 0)
	if err := json.Unmarshal(dataBytes, &data); err != nil {
		fmt.Println(err.Error(), "json unmarshal")
		return "", err
	}
	return cast.ToString(data["token"]), nil
}

//func loadFont(font string) error {
//	if font == "" {
//		font = "./static/fonts/stzhongs.ttf"
//	}
//	// 初始化字体
//	fontBytes, err := ioutil.ReadFile(font)
//	if err != nil {
//		return err
//	}
//	fontTypes, err = freetype.ParseFont(fontBytes)
//	if err != nil {
//		return err
//	}
//	return nil
//}

// WaterMarkTheory 添加水印
func WaterMarkTheory(data map[string]string, base64File, subject, code, photo_type, filePath string, size int) (imageURL string, err error) {
	if len(base64File) == 0 {
		return "", errors.New("照片为空")
	}
	if fontTypes == nil {
		if err := loadFont(""); err != nil {
			return "", err
		}
	}
	//log.Println(base64File)
	c := freetype.NewContext()
	c.SetFont(fontTypes)
	c.SetFontSize(float64(size))
	c.SetSrc(&image.Uniform{color.RGBA{R: uint8(227), G: uint8(23), B: uint8(13), A: uint8(255)}})
	fileByte, err := base64.StdEncoding.DecodeString(base64File)
	var (
		img   *image.RGBA
		img_g image.Image
		b     image.Rectangle
		m     *image.NRGBA
	)
	if subject == "1" || subject == "4" {
		img_g, err = imaging.Decode(bytes.NewReader(fileByte))
		if err != nil {
			return "", err
		}
		img_g = imaging.Fill(img_g, 520, 390, imaging.Center, imaging.Lanczos)
		b = img_g.Bounds()
		m = image.NewNRGBA(b)
		c.SetClip(b)
		c.SetDst(m)
		draw.Draw(m, b, img_g, image.ZP, draw.Src)
	} else {
		var (
			imgs image.Image
		)
		imgs, err = imaging.Decode(bytes.NewReader(fileByte))
		if err != nil {
			return "", err
		}

		img = image.NewRGBA(image.Rect(0, 0, 520, 390))
		ms := resize.Resize(0, 390, imgs, resize.Lanczos3)
		draw.Draw(img, img.Bounds(), ms, image.Pt(-125, 0), draw.Over)
		fmt.Println("school_name", data["school_name"])
		if data["school_name"] == "石家庄市都市机动车驾驶员培训学校" {
			img = (*image.RGBA)(imaging.Fill(img, 640, 480, imaging.Center, imaging.Lanczos))
		} else {
			img = (*image.RGBA)(imaging.Fill(img, 520, 390, imaging.Center, imaging.Lanczos))
		}
		b = img.Bounds()
		m = image.NewNRGBA(b)
		c.SetClip(b)
		c.SetDst(m)
		draw.Draw(m, b, img, image.ZP, draw.Src)
	}
	//var (
	//	imgs image.Image
	//	img  *image.RGBA
	//	b    image.Rectangle
	//	m    *image.NRGBA
	//)
	//imgs, err = imaging.Decode(bytes.NewReader(fileByte))
	//if err != nil {
	//	return "", err
	//}
	//
	//img = image.NewRGBA(image.Rect(0, 0, 520, 390))
	//ms := resize.Resize(0, 390, imgs, resize.Lanczos3)
	//draw.Draw(img, img.Bounds(), ms, image.Pt(-125, 0), draw.Over)
	//
	//img = (*image.RGBA)(imaging.Fill(img, 520, 390, imaging.Center, imaging.Lanczos))
	//
	//b = img.Bounds()
	//m = image.NewNRGBA(b)
	//c.SetClip(b)
	//c.SetDst(m)
	//draw.Draw(m, b, img, image.ZP, draw.Src)
	for k, v := range data {
		var (
			x, y int
		)
		if k == "school_name" {
			x = 5
			y = 15
		} else if k == "record_type" {
			x = 5
			y = b.Dy() - 5
		} else if k == "speed" {
			x = 5
			y = b.Dy() - 60
		} else if k == "lat" {
			x = 5
			y = b.Dy() - 32
		} else if k == "long" {

		} else if k == "type" {
			x = 5
			y = b.Dy() - 5
		} else if k == "date" {
			x = b.Dx() - int(float64(utf8.RuneCountInString(v))*float64(size)*0.56)
			y = 15
		} else if k == "subject" {
			x = b.Dx() - int(float64(utf8.RuneCountInString(v))*float64(size)*1.0)
			y = b.Dy() - 30
		} else if k == "student_name" {
			x = b.Dx() - int(float64(utf8.RuneCountInString(v))*float64(size)*1.0)
			y = b.Dy() - 18
		} else if k == "coach_name" {
			x = b.Dx() - int(float64(utf8.RuneCountInString(v))*float64(size)*1.0)
			y = b.Dy() - 5
		}
		pt := freetype.Pt(x, y)
		_, err := c.DrawString(v, pt)
		if err != nil {
			return "", err
		}
	}
	var buf bytes.Buffer

	jpeg.Encode(&buf, m, &jpeg.Options{80})

	var (
		client *oss.Client
		bucket *oss.Bucket
	)
	// 上传到oss
	conf, err := config.NewConfig("ini", "conf/app.conf")
	if err != nil {
		log.Fatal("配置文件载入错误")
	}

	ossSection, err := conf.GetSection("oss")
	if err != nil {
		log.Fatal("配置文件载入错误-数据库-section载入失败")
	}
	if client, err = oss.New(ossSection["oss_endpoint"], ossSection["oss_access_id"], ossSection["oss_access_key"]); err != nil {
		return "", err
	}
	if bucket, err = client.Bucket(ossSection["oss_bucket"]); err != nil {
		return "", err
	}

	// 构造文件名
	//random := GetRandoms(10)
	fileName := fmt.Sprintf("upload/%s/student/%s/%s/%s/%d%s%s", filePath, code, subject, time.Now().Format("20060102"), time.Now().Unix(), photo_type, ".jpg")
	if err = bucket.PutObject(fileName, bytes.NewReader(buf.Bytes())); err != nil {
		return "", err
	}
	return ossSection["oss_website"] + fileName, nil
}

func CreatCarCode(carType string) (code string) {
	switch carType {
	case "A1":
		code = "01"
	case "A2":
		code = "02"
	case "A2+":
		code = "02"
	case "A3":
		code = "03"
	case "B1":
		code = "11"
	case "B2":
		code = "12"
	case "B2+":
		code = "12"
	case "C1":
		code = "21"
	case "C2":
		code = "22"
	case "C3":
		code = "23"
	case "C4":
		code = "24"
	case "C5":
		code = "25"
	case "D":
		code = "31"
	case "E":
		code = "32"
	case "F":
		code = "33"
	case "M":
		code = "41"
	case "N":
		code = "42"
	case "P":
		code = "43"
	default:

	}
	return code
}

var TeacherTrainCarTypeNew = map[string][]string{
	"M":  {"A1", "A2", "B1", "B2", "M"},
	"F":  {"D", "E", "F"},
	"E":  {"D", "E"},
	"C6": {"A2"},
	"C4": {"A1", "A2", "A3", "B1", "B2", "C1", "C3", "C4"},
	"C5": {"A1", "A2", "A3", "B1", "B2", "C1", "C3", "C4", "C5"},
	"C3": {"A1", "A2", "A3", "B1", "B2", "C1", "C3"},
	"C2": {"A1", "A2", "A3", "B1", "B2", "C1", "C2"},
	"C1": {"A1", "A2", "A3", "B1", "B2", "C1"},
	"B2": {"A1", "A2", "B2"},
	"B1": {"A1", "A2", "B1"},
	"A2": {"A1", "A2"},
	"A3": {"A1", "A3"},
	"A1": {"A1"},
}

//截取字符串

func Substr(str string, start, length int) string {
	rs := []rune(str)
	rl := len(rs)
	end := 0

	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length

	if start > end {
		start, end = end, start
	}

	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}
	return string(rs[start:end])
}

var (
	// CarRecord 每个车型对应的学时
	CarRecordSet = map[string]map[string]int{
		"A1": {"1": 10, "2": 32, "3": 20, "4": 16},
		"B1": {"1": 10, "2": 32, "3": 20, "4": 16},
		"A2": {"1": 12, "2": 36, "3": 22, "4": 18},
		"A3": {"1": 14, "2": 47, "3": 33, "4": 20},
		"B2": {"1": 14, "2": 50, "3": 32, "4": 22},
		"C1": {"1": 12, "2": 16, "3": 24, "4": 10},
		"C2": {"1": 12, "2": 12, "3": 24, "4": 10},
		"C3": {"1": 12, "2": 14, "3": 16, "4": 8},
		"C4": {"1": 10, "2": 10, "3": 10, "4": 8},
		"D":  {"1": 10, "2": 10, "3": 10, "4": 8},
		"E":  {"1": 10, "2": 10, "3": 10, "4": 8},
		"F":  {"1": 10, "2": 10, "3": 10, "4": 8},
		"C5": {"1": 12, "2": 14, "3": 24, "4": 10},
	}
)

// CarRecordSetting 业务类型设置
func CarRecordSetting(province, car, option, subject string) (setting int) {
	if province == "510000" {
		switch subject {
		case "1":
			if car == "A2" || car == "B2" {
				setting = CarRecordSet[car]["1"] * 45
			} else {
				setting = CarRecordSet[car]["1"] * 45
			}
		case "2":
			setting = CarRecordSet[car][subject] * 45
		case "3":
			if car == "C1" || car == "C2" {
				setting = CarRecordSet[car][subject] / 2 * 45
			} else {
				setting = CarRecordSet[car][subject] * 45
			}

		case "4":
			if car == "A2" || car == "B2" {
				setting = CarRecordSet[car]["1"] * 45
			} else {
				setting = CarRecordSet[car][subject] * 45
			}
		}
	} else if province == "370000" || province == "340000" {
		switch subject {
		case "1":
			if car == "A2" || car == "B2" {
				setting = CarRecordSet[car]["1"] * 45
			} else {
				setting = CarRecordSet[car]["1"] * 45
			}
		case "2":
			setting = CarRecordSet[car][subject] * 45
		case "3":
			if car == "C1" || car == "C2" {
				setting = CarRecordSet[car][subject] * 45
			} else {
				setting = CarRecordSet[car][subject] * 45
			}

		case "4":
			if car == "A2" || car == "B2" {
				setting = CarRecordSet[car]["1"] * 45
			} else {
				setting = CarRecordSet[car][subject] * 45
			}
		}
	} else if province == "520000" {
		if option == "11" || option == "12" {
			if subject == "1" {
				setting = 45 * 4
			} else if subject == "2" {
				setting = 45
			} else if subject == "4" {
				setting = 45 * 2
			}
		} else {
			if car == "C1" && subject == "2" {
				setting = 18 * 45
			} else if car == "C2" && subject == "2" {
				setting = 16 * 45
			} else {
				setting = CarRecordSet[car][subject] * 45
			}
		}
	} else {
		if option == "11" || option == "12" {
			if subject == "1" {
				setting = 45 * 4
			} else if subject == "2" {
				setting = 45
			} else if subject == "4" {
				setting = 45 * 2
			}
		} else {
			switch subject {
			case "1":
				if car == "A2" || car == "B2" {
					setting = (CarRecordSet[car]["1"] + 4) * 45
				} else {
					setting = CarRecordSet[car]["1"] * 45
				}
			case "2":
				if car == "A2" || car == "B2" {
					setting = (CarRecordSet[car]["2"] + 1) * 45
				} else {
					setting = CarRecordSet[car][subject] * 45
				}

			case "4":
				if car == "A2" || car == "B2" {
					setting = (CarRecordSet[car]["4"] + 2) * 45
				} else {
					setting = CarRecordSet[car][subject] * 45
				}
			}
		}
	}
	return
}
